package com.sec.android.app.myfiles.util;

import android.os.Environment;

import com.sec.android.app.myfiles.log.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;


public class GolfUtils {
    private static final String TAG = "GolfUtils";
    private static final String EXTENSION_JPG = ".jpg";
    private static final String EXTENSION_GOLF = ".golf";
    public static final String GOLF_TEMP_PATH = Environment.getExternalStorageDirectory().toString() + "/.thumbnails/golf/tmp";

    /**
     * This method is for generating Golf file to convert. This method is
     * similar to other applications's method. (EX. Gallery - GolfDecoder.java,
     * Camera-GolfViewerUtils.java) Therefore, this class doesn't follow a code
     * style.
     *
     * @param tempFilePath
     * @param FilePath
     * @param allFrame
     */

    public static String getJpgTempFilePath(String filePath, boolean allFrame) {
        try {
            File tmpDir = SemFwWrapper.file(GOLF_TEMP_PATH);
            if (!tmpDir.exists() && !tmpDir.mkdirs()) {
                Log.d(TAG, "getJpgTempFilePath : mkdir failed");
            }

            String fileName = filePath.substring(filePath.lastIndexOf(File.separator), filePath.lastIndexOf(EXTENSION_GOLF));
            StringBuilder strBuild = new StringBuilder(GOLF_TEMP_PATH);
            strBuild.append(fileName);
            strBuild.append('_');
            String tempPath = strBuild.toString();
            strBuild.append(0); // 1st frame only
            strBuild.append(EXTENSION_JPG);
            generateJpgFileFromGolf(tempPath, filePath, allFrame);
            return strBuild.toString();
        } catch (Exception e) {
            Log.e(TAG, "Exception:" + e.toString());
        }
        return null;
    }

    private static void generateJpgFileFromGolf(String tempFilePath, String filePath, boolean allFrame) {
        File f = SemFwWrapper.file(filePath);
        try (FileInputStream inStream = new FileInputStream(f)) {
                int len = (int) f.length();
                byte[] byteArray = new byte[len];
                int readLen = inStream.read(byteArray, 0, len);
                if (readLen <= 0) {
                    inStream.close();
                    return;
                }

                ByteBuffer byteBuf = ByteBuffer.wrap(byteArray);
                byteBuf.order(ByteOrder.nativeOrder());
                byteBuf.position(0);

                IntBuffer ib = byteBuf.asIntBuffer();
                ib.get(); // signature

                // retrieve header fields
                int ver_major = ib.get();
                int ver_minor = ib.get();

                // video sequence is supported from version 1.4
                if (ver_major < 1 || ver_minor < 4) {
                    return;
                }
                int header_length = ib.get();
                //int format = ib.get();
                int nFrames = ib.get();

                // read off irrelevant info.
                ib.get(); // centerX
                ib.get(); // centerY
                ib.get(); // fps
                ib.get(); // nFOIs
                // FOIs Array Start
                ib.get();
                ib.get();
                ib.get();
                ib.get();
                ib.get();
                ib.get();
                ib.get();
                ib.get();
                ib.get(); // FOIs Array End
                ib.get(); // w
                ib.get(); // h
                ib.get(); // log info

                int num_video_seq = 0;
                if (allFrame) {
                    num_video_seq = ib.get();
                    if (num_video_seq <= 0)
                        return;
                }

                byteBuf.position(header_length);
                if (ver_minor >= 2) {
                    // all header fields are retrieved and we are at the
                    // beginning position of body
                    IntBuffer ib1 = byteBuf.asIntBuffer();

                    // leave middle/DMZ
                    // ...
                    // need to read offset table from tail
                    // offset start in ib space "-1" for thumbnail
                    int offset_start_in_ib = ib1.remaining() - nFrames - num_video_seq - 1;

                    // read one more offset for final frame
                    int[] offsetArray = new int[num_video_seq + 1 + nFrames];
                    ib1.position(offset_start_in_ib);
                    ib1.get(offsetArray);
                    int count = allFrame ? (num_video_seq + 1 + nFrames) : 1;

                    for (int i = 0; i < count; ++i) {
                        int size = 0;
                        if (count == (num_video_seq + nFrames)) {
                            size = offset_start_in_ib - offsetArray[i];
                        } else {
                            size = offsetArray[i + 1] - offsetArray[i];
                        }

                        try {
                            byte[] data = new byte[size];
                            System.arraycopy(byteBuf.array(), offsetArray[i], data, 0, size);
                            saveBufferToFile(tempFilePath + i, size, data);
                        } catch (OutOfMemoryError e) {
                            Log.e(TAG, "OutOfMemoryError:" + e.toString());
                        }
                    }
                }
        } catch (Exception e) {
            Log.d(TAG, "generateGolfFile Exception : " + e.getMessage());
        }
    }

    private static void saveBufferToFile(String fileName, int size, byte[] buffer) {
        File fl = SemFwWrapper.file(fileName + EXTENSION_JPG);

        try (FileOutputStream stream = new FileOutputStream(fl)) {
            stream.write(buffer, 0, size);
            stream.flush();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "saveBufferToFile FileNotFoundException");
        } catch (IOException e) {
            Log.d(TAG, "saveBufferToFile IOException");
        }
    }
}
